<?php

namespace App\Utils;

class LoggerUtil
{
    private string $filePath;
    private string $dirName = BASE_PATH . '/runtime/logs/'; // 日志文件目录
    private float|int $maxFileSize = 2 * 1024 * 1024; // 2MB 文件大小限制
    private string $datePattern = 'Y-m-d'; // 日志文件命名中的日期格式
    private bool $rollingType = true; // true按文件大小滚动,false按日期滚动

    /**
     * 检查并执行日志文件的滚动
     */
    private function checkAndRollFile()
    {
        $dir_path = dirname($this->filePath);
        if (!file_exists($dir_path)) {
            mkdir($dir_path, 0755, true); // 0755 表示权限，true 表示递归创建
        }

        // 检查是否需要按日期滚动
        if (!$this->rollingType && file_exists($this->filePath) && date($this->datePattern) !== date($this->datePattern, filemtime($this->filePath))) {
            $this->rollByDate();
        }

        // 检查文件大小
        clearstatcache(true, $this->filePath);
        if ($this->rollingType && file_exists($this->filePath) && filesize($this->filePath) >= $this->maxFileSize) {
            $this->rollBySize();
        }
    }

    /**
     * 按日期滚动日志文件
     */
    private function rollByDate()
    {
        $newPath = $this->getNewFilePath(true);
        rename($this->filePath, $newPath);
    }

    /**
     * 按大小滚动日志文件
     */
    private function rollBySize()
    {
        $newPath = $this->getNewFilePath(false, true);
        rename($this->filePath, $newPath);
    }

    /**
     * 获取新日志文件的路径
     *
     * @param bool $byDate 是否按日期滚动
     * @param bool $forcedBySize 是否因文件大小强制滚动
     * @return string 新的日志文件路径
     */
    private function getNewFilePath($byDate = false, $forcedBySize = false)
    {
        $baseName = pathinfo($this->filePath, PATHINFO_FILENAME);
        $extension = pathinfo($this->filePath, PATHINFO_EXTENSION);
        $dirName = pathinfo($this->filePath, PATHINFO_DIRNAME);

        $suffix = '';
        if ($byDate) {
            $suffix = '_' . date($this->datePattern);
        } elseif ($forcedBySize) {
            $suffix = '_size_' . date('Hi');
        }

        return "{$dirName}/{$baseName}{$suffix}.{$extension}";
    }

    /**
     * 写入日志内容
     *
     * @param string $fileName
     * @param mixed $content
     * @param string $label
     * @return bool
     */
    public static function write(string $fileName, mixed $content, string $label = ''): bool
    {
        $instance = new self();
        $instance->filePath = $instance->dirName . date('Ymd') . '/' . $fileName . '.log';
        $instance->checkAndRollFile();
        if (is_string($content)) {
            $content = "[" . date("Y-m-d H:i:s") . "] " . $label . SPACE . $content . PHP_EOL;
        } else {
            $content = "[" . date("Y-m-d H:i:s") . "] " . $label . PHP_EOL . var_export($content, true) . PHP_EOL;
        }

        // 写入日志
        $result = file_put_contents($instance->filePath, $content, FILE_APPEND);

        return $result !== false;
    }


}